from datetime import datetime
from flask import Blueprint, jsonify, request, current_app
from werkzeug.security import generate_password_hash, check_password_hash
from application import db
from flask_jwt_extended import jwt_required, create_access_token, jwt_refresh_token_required, create_refresh_token, get_jwt_identity, fresh_jwt_required
from application.api.users.models import Users, WorkDetail, Rotation
from application.api.users.schemas import WorkSchema, UserSchema, RotationSchema
from application.common.status_code import *
from application.common.file_helper import is_allowed_zip
import os

api_users = Blueprint('users', __name__)

# 注册
@api_users.route('/register', methods=['POST'])
def register():
    json_data = request.get_json()
    json_data['password'] = generate_password_hash(json_data['password'])
    users_scehma = UserSchema()
    user = users_scehma.load(json_data)
    db.session.add(user)
    db.session.commit()
    return jsonify({'code': SUCCESS, 'message': '成功', 'data': {'user_id': user.id}})

# 登录
@api_users.route('/login', methods=['POST'])
def login():
    json_data = request.get_json()

    username = json_data['username']
    user = Users.query.filter_by(username=username).first()
    if user is None:
        return jsonify({'code': ERROR_USER_PASSWORD[0], 'message': ERROR_USER_PASSWORD[1]})
    if check_password_hash(user.password, json_data['password']):
        # 验证通过,分配jwt令牌, 生成一个新鲜的令牌
        jwt_token = create_access_token(identity=username, fresh=True)
        # 生成一个刷新用的token
        refresh_token = create_refresh_token(identity=username)
        return jsonify({'code': SUCCESS, 'message': '成功', 'token': jwt_token, 'refresh_token': refresh_token})
    return jsonify({'code': ERROR_USER_PASSWORD[0], 'message': ERROR_USER_PASSWORD[1]})

# 刷新token
@api_users.route('/refresh', methods=['POST'])
@jwt_refresh_token_required
def refresh():
    current_user = get_jwt_identity()
    # 取用户的状态，如果停用就不生成token
    user = Users.query.filter_by(username=current_user).first()

    result = {'code': ERROR_USER_INVALID[0], 'message': ERROR_USER_INVALID[1]}

    if user is not None and user.status == 1:
        result = {'code': SUCCESS, 'message': '成功', 'access_token': create_access_token(identity=current_user, fresh=False)}

    return jsonify(result)

# 上传作品
@api_users.route('/work', methods=['POST'])
@jwt_required
def upload_work():
    current_user = get_jwt_identity()
    user = Users.query.filter_by(username=current_user).first()
    if user.user_type is not 1:
        return jsonify({'code': ERROR_USER_TYPE[0], 'message': ERROR_USER_TYPE[1]})
    if user.work is not None:
        return jsonify({'code': ERROR_RESOUCE_EXISTS[0], 'message': ERROR_RESOUCE_EXISTS[1]})
    file = request.files.get('work')
    # 检查文件类型,是否是压缩文件
    print(file.content_type)
    if not is_allowed_zip(file.content_type):
        return jsonify({'code': ERROR_FILE_TYPE[0], 'message': ERROR_FILE_TYPE[1]})

    # 生成文件名和文件路径
    ext = file.filename.split('.')[-1]
    filename = str(user.id)
    full_filename = filename + '.' + ext
    filepath = current_app.config['UPLOAD_PATH']
    # 保存文件
    full_filepath = os.path.join(filepath, full_filename)
    file.save(full_filepath)
    work = WorkDetail()
    work.name = full_filename
    work.user_id = user.id
    work.upload_time = datetime.now()
    rotation = Rotation()
    rotation.user_id = user.id
    db.session.add(rotation)
    db.session.add(work)
    db.session.commit()

    return jsonify({'code': SUCCESS, 'message': '成功'})

# 打分
@api_users.route('/rate/<int:user_id>,<int:round>', methods=['PUT'])
@jwt_required
def rate(user_id, round):
    current_user = get_jwt_identity()
    # 判断用户是否是评委
    user = Users.query.filter_by(username=current_user).first()
    if user.jurisdiction is 0:
        return jsonify({'code': ERROR_RATE_END[0], 'message': ERROR_RATE_END[1]})
    if user.user_type is not 2:
        return jsonify({'code': ERROR_USER_TYPE[0], 'message': ERROR_USER_TYPE[1]})
    # 判断是否有该作品
    work = WorkDetail.query.filter_by(user_id=user_id).first()
    if work is None:
        return jsonify({'code': ERROR_WORK_FIND[0], 'message': ERROR_WORK_FIND[1]})
    # 判断是否有参赛资格
    if user.qualification is 0:
        return jsonify({'code':ERROR_WORK_NO_QUALIFICATION[0], 'message': ERROR_WORK_NO_QUALIFICATION[1]})
    json_data = request.get_json()
    work.rater = current_user
    work.rating_time = datetime.now()
    work.score = json_data['score']
    ration = Rotation.query.filter_by(user_id=user_id).first()
    ration.user_id = user_id
    if round == 1:
        if ration.first_round is not None:
            return jsonify({'code': ERROR_RATE_REPEAT[0], 'message': ERROR_RATE_REPEAT[1]})
        ration.first_round = json_data['score']
    if round == 2:
        if ration.second_round is not None:
            return jsonify({'code': ERROR_RATE_REPEAT[0], 'message': ERROR_RATE_REPEAT[1]})
        ration.second_round = json_data['score']
    if round == 3:
        if ration.final_round is not None:
            return jsonify({'code': ERROR_RATE_REPEAT[0], 'message': ERROR_RATE_REPEAT[1]})
        ration.final_round = json_data['score']
    if json_data['score'] > 10 or json_data['score'] < 0:
        return jsonify({'code': ERROR_OUT_OF_RANGE[0], 'message': ERROR_OUT_OF_RANGE[1]})
    if isinstance(json_data['score'], int) is False:
        return jsonify({'code': ERROR_MUST_INT[0], 'message': ERROR_MUST_INT[1]})
    if round not in [1,2,3]:
        return jsonify({'code': ERROR_RETE_ROUND[0], 'message': ERROR_RETE_ROUND[1]})
    db.session.add(ration)
    db.session.add(work)
    db.session.commit()
    return jsonify({'code': SUCCESS, 'message': '成功'})

# 查看所有参赛用户评分
@api_users.route('/rating', methods=['GET'])
@jwt_required
def get_ratings():
    work = WorkDetail.query.filter(WorkDetail.score != None)
    work_schema = WorkSchema(many=True)
    json_data = work_schema.dump(work)
    data = {'code': SUCCESS, 'message': '成功', 'data': json_data}
    return jsonify(data)

# 查看单个参赛用户评分
@api_users.route('/rating/<int:user_id>', methods=['GET'])
@jwt_required
def get_rating(user_id):
    work = WorkDetail.query.get(user_id)
    if work.score is None:
        return jsonify({'code': ERROR_RATE_NOT_YET[0], 'message': ERROR_RATE_NOT_YET[1]})
    work_schema = WorkSchema()
    json_data = work_schema.dump(work)
    data = {'code': SUCCESS, 'message': '成功', 'data': json_data}
    return jsonify(data)


# 查看排行
@api_users.route('/rank', methods=['GET'])
@jwt_required
def get_rank():
    rank = WorkDetail.query.filter(WorkDetail.score != None).order_by(WorkDetail.score.desc())
    work_schema = WorkSchema(many=True, only=['name', 'score', 'rater'])
    json_data = work_schema.dump(rank)
    data = {'code': SUCCESS, 'message': '成功', 'data': json_data}
    return jsonify(data)

# 评分开始
@api_users.route('/begin', methods=['PUT'])
@jwt_required
def begin_rate():
    current_user = get_jwt_identity()
    user = Users.query.filter_by(username=current_user).first()
    if user.user_type is not 3:
        return jsonify({'code': ERROR_USER_TYPE[0], 'message': ERROR_USER_TYPE[1]})
    Users.query.filter_by(jurisdiction=0).update({'jurisdiction': 1})

    db.session.commit()
    return jsonify({'code': SUCCESS, 'message': '成功'})

# 结束评分
@api_users.route('/end', methods=['PUT'])
@jwt_required
def edn_rate():
    current_user = get_jwt_identity()
    user = Users.query.filter_by(username=current_user).first()
    if user.user_type is not 3:
        return jsonify({'code': ERROR_USER_TYPE[0], 'message': ERROR_USER_TYPE[1]})
    Users.query.filter_by(jurisdiction=1).update({'jurisdiction': 0})
    db.session.commit()
    return jsonify({'code': SUCCESS, 'message': '成功'})

# 查看参赛选手所有评选分数
@api_users.route('/rating_all/<int:user_id>', methods=['GET'])
@jwt_required
def rating_all(user_id):
    rotation = Rotation.query.get(user_id)
    rotation_schema = RotationSchema(only=['users', 'first_round', 'second_round', 'final_round'])
    json_data = rotation_schema.dump(rotation)
    data = {'code': SUCCESS, 'message': '成功', 'data': json_data}
    return jsonify(data)

# 取消参赛资格
@api_users.route('/cancel/<int:user_id>', methods=['PUT'])
@jwt_required
def work_cancel(user_id):
    current_user = get_jwt_identity()
    user = Users.query.filter_by(username=current_user).first()
    if user.user_type is not 3:
        return jsonify({'code': ERROR_USER_TYPE[0], 'message': ERROR_USER_TYPE[1]})
    Users.query.filter_by(id=user_id).update({'qualification': 0})

    db.session.commit()
    return jsonify({'code': SUCCESS, 'message': '成功'})